package br.com.educa.json;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class FromJsonToObject {

	@Around("execution(public * br.com.educa..fromJsonTo*(..))")
	public Object completeFromJsonTo(ProceedingJoinPoint pjp) throws Throwable {

		Object object = pjp.proceed();

		object = completeObject(object);

		return object;

	}



	@SuppressWarnings("rawtypes")
	public Object completeObject(Object object){
		try {

			Field[] fields = object.getClass().getDeclaredFields();

			for (Field field : fields) {
				Annotation[] annotations = field.getAnnotations();
				for (Annotation annotation : annotations) {
					if(annotation.toString().contains("javax.persistence.ManyToOne")){
						field.setAccessible(true);
						Object inner = field.get(object);
						if(inner!=null){
							inner = completeObject(inner);
							Field id = inner.getClass().getDeclaredField("id");
							id.setAccessible(true);
							Object value = id.get(inner);
							if(value!=null){
								Method[] methods = inner.getClass().getMethods();
								for (Method method : methods) {
									if(method.getName().equals("find"+inner.getClass().getSimpleName() ) ){
										method.setAccessible(true);
										Object args[] = new Object[1];
										args[0]=value;
										Object result= method.invoke(inner,args);
										field.set(object, result);
										break;
									}
								}
							}
						}
					}else if(annotation.toString().contains("javax.persistence.OneToMany") ||annotation.toString().contains("javax.persistence.ElementCollection") || annotation.toString().contains("javax.persistence.ManyToMany")){
						
						field.setAccessible(true);
						Object innerList = field.get(object);
						if(innerList!=null && innerList instanceof Collection){
							Collection innerListCollection = (Collection) innerList;
							for (Object objectInCollection : innerListCollection) {
								if(objectInCollection!=null){
									objectInCollection=completeObject(objectInCollection);
								}
							}
						}
						
					}
				}

			}

		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return object;
	}

}